﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Data;

namespace DXL_Library
{
    [Serializable]
    public class DXL_Grid
    {
        public bool NombreFijo;

        public bool PrimerRenglonConTitulos;

        public List<string> ValoresPrimerColumna;

        public List<string> FormatosColumna
        {
            get;
            set; 
        }
        
        private List<string> _tiposColumnas;

        public List<string> TiposColumnas
        {
            get { return _tiposColumnas; }
            set {
                List<string> aux;
                aux = value;

                if (aux != null)
                {
                    int i;
                    _tiposColumnas = new List<string>(aux.Count);

                    i = 0;
                    foreach (String tipo in aux)
                    {
                        //si noes un tipo de datos con la ruta completa (sytem.XXX)!!
                        if( ! tipo.Contains('.'))
                        {
                            _tiposColumnas.Add(string.Format("System.{0}", tipo));
                        }
                        i++;
                    }
                }
            }
        }
        public string TipoNombreAmigable(string tipoInterno)
        {
            string resp;

            resp = "SIN TIPO ERROR";

            if(tipoInterno == "System.DateTime")
            {
                resp = "FECHA" ;
            }
            if(tipoInterno == "System.String")
            {
                resp = "TEXTO" ;
            }
            if(tipoInterno == "System.Decimal")
            {
                resp = "NUMERO" ;
            }
            

            return resp;
        }
        public bool SinDatos()
        {
            return ((this.Datos == null) || (this.Datos.Rows == null) || (this.Datos.Rows.Count == 0));
        }


        private List<string> _titulosColumnas;

        public List<string> TitulosColumnas
        {
            get { return _titulosColumnas; }
            set 
            { 
                _titulosColumnas = value;

                //si ya tenia columnas
                if ((this.Datos != null) && (this.Datos.Columns != null))
                {
                    this.Datos.Columns.Clear();
                }
                //si no hay aun un datatable asociado a los datos
                if (this.Datos == null)
                {
                    this.Datos = new DataTable();
                }

                foreach (String col in _titulosColumnas)
                {
                    
                    this.Datos.Columns.Add(col);
                }
            }
        }
        /// <summary>
        /// Prepara datos teniendo una columna fija de titulos
        /// </summary>
        /// <param name="prefijo"></param>
        /// <param name="numFil"></param>
        public void DatosRandom(string prefijo, int numFil)
        {
            bool exito;


            exito = Util.DatosRandom(this.Datos, prefijo, numFil);

            if (!exito)
            {
                throw new Exception("Error al crear datos aleatorios");
            }
          
        }
        public bool DatosRandomPrimeraColumnaFija(string prefijo, out string msg)
        {
            int i ;
            int j ;
            DataRow dr ;
            int numCol ;
            bool exito;

            numCol =this.Datos.Columns.Count ;
            exito = false;
            msg = string.Empty;

            if (this.ValoresPrimerColumna == null)
            {
                msg = "Para poder generar datos debe especificar valores fijos, en el archivo de especificaciones,para la primera columna lo cual determina el numero de filas" ;

                msg += "Considere usar los metodos de Util.DatosRadom";
            }
            else
            {
                for (j = 0; j < this.ValoresPrimerColumna.Count; j++)
                {
                    dr = this.Datos.NewRow();

                    for (i = 0; i < numCol; i++)
                    {
                        if (i == 0)
                        {
                            dr[i] = ValoresPrimerColumna[j];
                        }
                        else
                        {
                            dr[i] = string.Format("{0}{1}", prefijo, (j * numCol + i + 1));
                        }

                    }


                    this.Datos.Rows.Add(dr);
                }
                exito = true;
            }
            return exito;
        }
        
        private int _numGrilla;

        public int NumGrilla
        {
            get { return _numGrilla; }
            set { _numGrilla = value; }
        }

        private string _nombre;


        /// <summary>
        /// El nombre con el que se conocera este rango/grilla de datos "lista de productos"
        /// </summary>
        public string Nombre
        {
            get { return _nombre; }
            set { _nombre = value; }
        }


        /// <summary>
        /// Contiene el rango de donde se cargaron los datos por ejemplo "A2:B4"
        /// </summary>
        private string _rango;

        public string Rango
        {
            get { return _rango; }
            set { _rango = value; }
        }

        private DataTable _datos;

        public DataTable Datos
        {
            get { return _datos; }
            set { _datos = value; }
        }

        private string _Titulos;

        public string TitulosRango
        {
            get { return _Titulos; }
            set { _Titulos = value; }
        }


        private bool _toStringMuestraDatos;

        public bool ToStringMuestraDatos
        {
            get { return _toStringMuestraDatos; }
            set { _toStringMuestraDatos = value; }
        }
        public DXL_Grid()
        {
            ToStringMuestraDatos = false;
        }
        public override string ToString()
        {
            string resp;
            string strDatos;


            resp = string.Format("Grilla:{0}, Rango:{1}, DATOS...", Nombre, Rango);

            strDatos = string.Empty;

            if (this.Datos != null)
            {
                if (ToStringMuestraDatos)
                {
                    foreach (DataRow dr in this.Datos.Rows)
                    {
                        strDatos += "\t";
                        for (int i = 0; i < this.Datos.Columns.Count; i++)
                        {
                            strDatos += dr[i].ToString() + ",";
                        }
                    }
                }
                else
                {
                    strDatos += "(coloque la propiedad ToStringMuestraDatos en true)";
                }


            }
            else
            {
                strDatos = "SIN DATOS";
            }

            return resp + strDatos;
        }
        /// <summary>
        /// Hace transposicion de los datos, tomando la primera columna y convirtiendola en los nombres columnas
        /// </summary>
        /// <returns></returns>
        public bool TransponerDatos()
        {
            bool exito;
            DataTable aux;

            aux = Util.TrasponerDatos(this.Datos, out exito);

            if (exito)
            {
                this.Datos = aux;
            }
            else
            {
                throw new Exception("Error al hacer la transposicion de datos");
            }

            return exito;
        }
        public string Query(DXL_Sheet h)
        {
            string resp;

            if (h == null)
            {
                throw new ArgumentException("el parametro hoja no puede ser null");
            }


            if (this.TitulosRango.StartsWith("-"))
            {

                //                                  [NOMBRE_HOJA$RANGO]
                //                                  [MENSUAL$A5:A22]

                resp = String.Format("SELECT * FROM [{0}${1}]", h.Nombre, this.Rango);
            }
            else
            {

                /*
    SELECT F1,F2,F3, F4 
    FROM [Accounts$A7:D7] 
    UNION ALL 
    SELECT F1, F2, F3, '' As F4 
    FROM [Accounts$E8:G8]
    */

                //WORKS
                resp = String.Format("SELECT * FROM [{0}${1}] UNION ALL SELECT * FROM [{0}${2}] ", h.Nombre, this.TitulosRango, DXL_Grid.RangoQuickFix(this.Rango));
            }
            return resp;
        }
        public bool ConTitulos()
        {
            bool resp ;

            resp = (Util.CadenaConTexto(this.TitulosRango) || (this.TitulosColumnas != null));

            return resp;
        }
        public string QueryTitulos(DXL_Sheet h)
        {
            string resp;
            string rangoTitulos;

            if (h == null)
            {
                throw new ArgumentException("el parametro hoja no puede ser null");
            }

            //se especificaron TITULOS
            if (  this.ConTitulos())
            {
                rangoTitulos = this.TitulosRango;
            }
            else
            {
                //no se le especificaron unos titulos por aparte de los DATOS..es decir los titulos son la primera fila de los datos
                rangoTitulos = this.RangoPrimeraFila();
                
            }

            resp = String.Format("SELECT * FROM [{0}${1}]", h.Nombre, rangoTitulos);

            return resp;
        }
        public string RangoPrimeraFila()
        {
            int iniFil;
            string iniCol;
            int finFil;
            string finCol;
            string rangoPimeraFila;

            DXL_Library.PartirRango(this.Rango, out iniCol, out iniFil, out finCol, out finFil);

            rangoPimeraFila = DXL_Library.CrearRango(iniCol, iniFil, finCol, iniFil);

            return rangoPimeraFila;
        }       
        public string QueryNombre(DXL_Sheet h)
        {
            string resp;

            //                                  [NOMBRE_HOJA$RANGO]
            //                                  [MENSUAL$A22:A22]
            resp = String.Format("SELECT * FROM [{0}${1}:{1}]", h.Nombre, this.Nombre);
            return resp;
        }
        public string QueryPorRenglon(int numRenglon, DXL_Sheet h)
        {
            string resp;
            string iniCol;
            string finCol;
            int iniFil;
            int finFil ;
            //                                  [NOMBRE_HOJA$RANGO]
            //                                  [MENSUAL$A5:A22]

            DXL_Library.PartirRango(this.Rango, out iniCol, out iniFil, out finCol, out finFil);

            string rango;
            int renglonActual;

            renglonActual = iniFil + numRenglon ;

            rango = DXL_Library.CrearRango(iniCol, renglonActual - 1, finCol, renglonActual);

            resp = String.Format("SELECT * FROM [{0}${1}]", h.Nombre, rango);
            return resp;
        }
        public object ValorDeRango(int fila, int columna)
        {
            object val;

            val = null;

            if (this.Datos != null)
            {
                try
                {
                    val = this.Datos.Rows[fila][columna];
                }
                catch
                {
                    val = null;
                }

            }

            return val;
        }
        public int NumFilasRango()
        {
            return DXL_Library.NumFilasRango(this.Rango);
        }
        public int NumColumnasRango()
        {
            return DXL_Library.NumColumnasRango(this.Rango);
        }
        public void PartirRango(out string celdaUno, out string celdaDos)
        {
            DXL_Library.PartirRango(this.Rango, out celdaUno, out celdaDos);
        }

        /// <summary>
        /// Esta funcio toma el rango DE DATOS especificado del archivo de especificacion (GARANTIAS.TXT) y devuelve un rango que incluye la primera fila
        /// </summary>
        /// <returns></returns>
        private static string RangoQuickFix(string unRangoExcel)
        {

            string parteAlfabetica;
            int parteNumerica;
            string primeraParteRango;
            int unRenglonArriba;
            string[] strRango;

            strRango = unRangoExcel.Split(':');
            primeraParteRango = strRango[0];

            int i;

            //determinar en donde empieza la parte numerica del la primera parte de rango AA78 (AA y 78)
            for (i = 0; (i < primeraParteRango.Length) && Char.IsLetter(primeraParteRango[i]); i++)
            {
                //esLetra = ; ESTO FUNCIONA. !
            }
            parteAlfabetica = primeraParteRango.Substring(0, i);
            parteNumerica = int.Parse(primeraParteRango.Substring(i));

            unRenglonArriba = parteNumerica;
            if (parteNumerica >= 2)
            {
                unRenglonArriba = parteNumerica - 1;
            }
            //armar de nuevo el rango incluyendo el renglon de arriba !! 
            primeraParteRango = parteAlfabetica + unRenglonArriba + ":" + strRango[1];

            return primeraParteRango;
        }


    }
}